from pygame import mixer
from aip import AipSpeech
from aip import AipImageClassify
from aip import AipOcr
from aip import AipFace
from rpi_ws281x import PixelStrip, Color
import time
from picamera import PiCamera
import pyaudio
import wave
import os
import sys
import snowboydecoder
import signal
import RPi.GPIO as GPIO
import serial
import base64
import eyed3
import requests
import json
import board
import neopixel

base_path = '/home/pi/source/'

def set_client_speech(API_ID = '18165866', API_KEY = 'gG8lKd6lywWScK7HFUHzZ5Ip', SECRET_KEY = 'wYzuK7pSXfnkFRt2Qpi3PaSvHCdhuzWh'):
    client = AipSpeech(API_ID, API_KEY, SECRET_KEY)
    return client

def set_client_image(API_ID = '18180053', API_KEY = 'YBFkpR9V83uj9DT9NDv6b3qG', SECRET_KEY = 'ckXdQ7SislH6ene6oTYBeF6DvpffsrAd'):
    client = AipImageClassify(API_ID, API_KEY, SECRET_KEY)
    return client

def set_client_ocr(API_ID = '19365161', API_KEY = 'cCOQeSYvjrkOwYePxqQv4Gkb', SECRET_KEY = 'cPSOPcKlVvQWBIa6zzqNWGdD2UIpwGaM'):
    client = AipOcr(API_ID, API_KEY, SECRET_KEY)
    return client

def set_client_face(API_ID = '19365849', API_KEY = 'fZ2Rgr1OaC7W0Qhi2cPtCPkl', SECRET_KEY = 'MMv0GYPH9ZdFIxUrLxtUZ4VbbbWN3CUS'):
    client = AipFace(API_ID, API_KEY, SECRET_KEY)
    return client

def synthesis(client, text, path, vol = 5, speed = 4, pit = 5, per = 0):
    result = client.synthesis(text,"zh",1,{"vol":vol,"spd":speed,"pit":pit,"per":per,})
    if not isinstance(result, dict):
        with open(base_path + '{0}.mp3'.format(path),'wb') as f:
            f.write(result)


def playAudio1(name):
    voice_file = eyed3.load(base_path+name)
    secs = voice_file.info.time_secs + 0.3
    mixer.init()
    mixer.music.load(base_path + name)
    mixer.music.play()
    time.sleep(secs)
    mixer.music.stop()

def playAudio(name,secs):
    mixer.init()
    mixer.music.load(base_path + name)
    mixer.music.play()
    time.sleep(secs)
    mixer.music.stop()

def mixer_load(path):
    mixer.init()
    mixer.music.load(base_path + path)

def mixer_play():
    mixer.music.play()

def mixer_rewind():
    mixer.music.rewind()

def mixer_stop():
    mixer.music.stop()

def mixer_pause():
    mixer.music.pause()

def mixer_unpause():
    mixer.music.unpause()

def mixer_set_volume(vol):
    vol = vol/100
    mixer.music.set_volume(vol)

def mixer_get_volume():
    return int(mixer.music.get_volume()*100)

def mixer_get_busy():
    return mixer.music.get_busy()

def read_file(path):
    b = open(base_path + path,'r',encoding='UTF-8')
    return b

def get_file_content(filePath):
    with open(base_path + filePath, 'rb') as fp:
        return fp.read()

def get_file_content64(filePath):
    with open(base_path + filePath, 'rb') as fp:
        return base64.b64encode(fp.read())

def audio_recog(client, path):
    result = client.asr(get_file_content(path), 'pcm', 16000, {
    'dev_pid': 1536,
})
    return result

def face_result(result, action):
    if action == "age":
        final = result['result']['face_list'][0]['age']
    elif action == "expression":
        expression = result['result']['face_list'][0]['expression']['type']
        if expression == 'laugh':
            final = "大笑"
        elif expression == 'smile':
            final = "微笑"
        else:
            final = "平静"
    elif action == "beauty":
        final = result['result']['face_list'][0]['beauty']
    elif action == "gender":
        gender = result['result']['face_list'][0]['gender']['type']
        if gender == 'male':
            final = "男性"
        else:
            final = "女性"
    elif action == "glasses":
        glasses = result['result']['face_list'][0]['glasses']['type']
        if glasses == 'none':
            final = "没带眼镜"
        elif glasses == 'sun':
            final = "墨镜"
        else:
            final = "普通眼镜"
    return final

def image_recog(client, path):
    image = get_file_content(path)
    result = client.advancedGeneral(image);
    return result

def plate_recog(client, path):
    image = get_file_content(path)
    result = client.licensePlate(image);
    return result


def words_recog(client, path):
    image = get_file_content(path)
    result = client.basicGeneral(image);
    return result

def face_recog(client, path):
    image1 = get_file_content64(path)
    image = str(image1,'utf-8')
    imageType = "BASE64"
    options = {}
    options["max_face_num"] = 2
    options["face_field"] = "age,expression,beauty,gender,glasses"
    result = client.detect(image,imageType,options);
    return result

def Tuling(tet):
    url = "http://openapi.tuling123.com/openapi/api/v2"
    data = {
        "perception":
    {
        "inputText":
        {
            "text": tet
        }
    },

    "userInfo":
    {
        "apiKey": "076e5d85de8c43fe977057baf8de2617",
        "userId": "123"
    }
        }
    res = requests.post(url=url,data=json.dumps(data))
    answer = res.json()
    try:
        val = answer["results"][0]["values"]["text"]
    except:
        return "请再说一次"
    else:
        return val



def image_get(path):
    camera = PiCamera()
    camera.start_preview()
    time.sleep(3)
    camera.capture(base_path + path)
    camera.stop_preview()
    camera.close()

def audio_get(path,time):
    print("Recording...")
    #print('arecord -d {0} -t wav -r 16000 -f S32_LE {1}'.format(time,path))
    os.system('arecord -d {0} -c 1 -t wav -r 16000 -f S16_LE {1}'.format(time,base_path + path))

    print('Done')

def audio_recog_bool(result):
    if result['err_no'] == 0:
        return True
    else:
        return False

def audio_recog_result(result):
    if result['err_no'] == 0:
        return result['result'][0]
    else:
        return "没听见"

def audio_get1(path,time):
    os.close(sys.stderr.fileno())
    CHUNK = 512
    FORMAT = pyaudio.paInt16
    CHANNELS = 1
    RATE = 16000
    RECORD_SECONDS = time
    WAVE_OUTPUT_FILENAME = base_path + path+".wav"

    p = pyaudio.PyAudio()

    stream = p.open(format=FORMAT,
                    channels=CHANNELS,
                    rate=RATE,
                    input=True,
                    frames_per_buffer=CHUNK)

    print("recording...")

    frames = []

    for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
        data = stream.read(CHUNK)
        frames.append(data)

    print("done")

    stream.stop_stream()
    stream.close()
    p.terminate()

    wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(p.get_sample_size(FORMAT))
    wf.setframerate(RATE)
    wf.writeframes(b''.join(frames))
    wf.close()

#语音唤醒

interrupted = False

def signal_handler(signal, frame):
    global interrupted
    interrupted = True

def interrupt_callback():
    global interrupted
    return interrupted

# 热词唤醒

def callbacks(detected):
    global detector

    # 语音唤醒后，提示ding两声
    # snowboydecoder.play_audio_file()
#    mixer.init()
#
#    mixer.music.load('./resources/ding.wav')#text文字转化的语音文件
#    mixer.music.play()
#    while mixer.music.get_busy() == True:
#        print('waiting')
#    #snowboydecoder.play_audio_file()
#    mixer.music.stop()
    #  关闭snowboy功能
    print(1111)
    detector.terminate()
    #执行功能
    detected()
    # 打开snowboy功能
    wake_up()    #   递归调用

def wake_up(detected, sen):

    global detector
    #os.close(sys.stderr.fileno())
    model = '/home/pi/.edublocks/resources/models/xiaobai.pmdl'  #  唤醒词为 SnowBoy
    # capture SIGINT signal, e.g., Ctrl+C
    signal.signal(signal.SIGINT, signal_handler)

    # 唤醒词检测函数，调整sensitivity参数可修改唤醒词检测的准确性
    detector = snowboydecoder.HotwordDetector(model, sensitivity=sen)

    print('请使用唤醒词小白')
    # main loop
    # 回调函数 detected_callback=snowboydecoder.play_audio_file
    # 修改回调函数可实现我们想要的功能
    detector.start(detected_callback=detected,      # 自定义回调函数
                   interrupt_check=interrupt_callback,
                   sleep_time=0.03)
    # 释放资源
    detector.terminate()

def buzzer_on(buzzer,init_value=0.5):
    buzzer.value=init_value
    time.sleep(0.01)

def buzzer_off(buzzer):
    buzzer.off()

# Define functions which animate LEDs in various ways.
def set_strip(pin,num = 1,bright = 64):
    strip = PixelStrip(num, pin, 800000, 10, False, bright, 0)
    return strip

def rgbled_init(pin):
#    strip = neopixel.NeoPixel(board.D10, 1)
    strip = set_strip(pin,1)
    strip.begin()
    return strip

def rgbled_action(strip, color):
    #strip[0] = color
    strip.setPixelColor(0,color)
    strip.show()
    time.sleep(0.01)

def colorWipe(strip, color, wait_ms=50):
    """Wipe color across display a pixel at a time."""
    for i in range(strip.numPixels()):
        strip.setPixelColor(i, color)
        strip.show()
        time.sleep(wait_ms / 1000.0)


def theaterChase(strip, color, wait_ms=50, iterations=10):
    """Movie theater light style chaser animation."""
    for j in range(iterations):
        for q in range(3):
            for i in range(0, strip.numPixels(), 3):
                strip.setPixelColor(i + q, color)
            strip.show()
            time.sleep(wait_ms / 1000.0)
            for i in range(0, strip.numPixels(), 3):
                strip.setPixelColor(i + q, 0)


def wheel(pos):
    """Generate rainbow colors across 0-255 positions."""
    if pos < 85:
        return Color(pos * 3, 255 - pos * 3, 0)
    elif pos < 170:
        pos -= 85
        return Color(255 - pos * 3, 0, pos * 3)
    else:
        pos -= 170
        return Color(0, pos * 3, 255 - pos * 3)


def rainbow(strip, wait_ms=20, iterations=1):
    """Draw rainbow that fades across all pixels at once."""
    for j in range(256 * iterations):
        for i in range(strip.numPixels()):
            strip.setPixelColor(i, wheel((i + j) & 255))
        strip.show()
        time.sleep(wait_ms / 1000.0)


def rainbowCycle(strip, wait_ms=20, iterations=5):
    """Draw rainbow that uniformly distributes itself across all pixels."""
    for j in range(256 * iterations):
        for i in range(strip.numPixels()):
            strip.setPixelColor(i, wheel(
                (int(i * 256 / strip.numPixels()) + j) & 255))
        strip.show()
        time.sleep(wait_ms / 1000.0)


def theaterChaseRainbow(strip, wait_ms=50):
    """Rainbow movie theater light style chaser animation."""
    for j in range(256):
        for q in range(3):
            for i in range(0, strip.numPixels(), 3):
                strip.setPixelColor(i + q, wheel((i + j) % 255))
            strip.show()
            time.sleep(wait_ms / 1000.0)
            for i in range(0, strip.numPixels(), 3):
                strip.setPixelColor(i + q, 0)


#自启动
def auto_start(opt):
    os.system('sudo systemctl {0} testboot.service  '.format(opt))


#数码管

def segment_init(sda,scl):
    global SDA ,SCL
    SDA = sda
    SCL = scl
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    GPIO.setup(SDA,GPIO.OUT)
    GPIO.output(SDA,0)
    time.sleep(0.0001)

def segment_start():
    GPIO.setup(SDA,GPIO.OUT)
    GPIO.output(SDA,0)
    time.sleep(0.0001)

def segment_send_byte(dat:int):
    GPIO.setup(SDA,GPIO.OUT)
    GPIO.setup(SCL,GPIO.OUT)
    for i in range(8):
        GPIO.output(SCL,0)
        if (int(dat) & 0x01):
            GPIO.output(SDA,1)
        else:
            GPIO.output(SDA,0)
        dat = dat >> 1
        time.sleep(0.0001)
        GPIO.output(SCL,1)
        time.sleep(0.0001)

def segment_read_byte():
    GPIO.setup(SDA,GPIO.IN)
    GPIO.setup(SCL,GPIO.OUT)
    dat = 0
    for i in range(8):
        GPIO.output(SCL,0)
        time.sleep(0.0001)
        GPIO.output(SCL,1)
        dat = dat >> 1

        if GPIO.input(SDA):
            dat |= 0x80
        time.sleep(0.0001)
    return dat

def coolguy_send_segment(num):
    num_int = (num * 10)
    if not(num_int %10):
        num_int = num_int / 10;
        Digitalflag = 0x01;
    else:
        num_int = num_int % 10000;
        Digitalflag = 0x02
    num1 = int(num_int / 1000)
    num2 = int((num_int % 1000) / 100)
    num3 = int(((num_int % 1000) % 100) / 10)
    num4 = int(((num_int % 1000) % 100) % 10)

    segment_start()
    segment_send_byte(0x05)
    segment_send_byte(num1)
    segment_send_byte(num2)
    segment_send_byte(num3)
    segment_send_byte(num4)
    segment_send_byte(Digitalflag)
    i = segment_read_byte()

    time.sleep(1)

def coolguy_send_segment2(num1,num2):
    segment_start()
    segment_send_byte(0x02)
    segment_send_byte(num1)
    segment_send_byte(num2)
    i = segment_read_byte()

#多路语音模块

def wtr050_sendbyte(val):
    GPIO.setup(wtr050_pin,GPIO.OUT)
    time.sleep(0.000104)
    for i in range(8):
        if ( val & 0x01):
            GPIO.output(wtr050_pin,1)
        else:
            GPIO.output(wtr050_pin,0)
        time.sleep(0.00006)
        val >> 1
    GPIO.output(wtr050_pin,1)
    time.sleep(0.000104)


def wtr050_Init(pin):
    global wtr050_pin
    wtr050_pin = pin
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(wtr050_pin,GPIO.OUT)
    GPIO.output(wtr050_pin,1)
    time.sleep(0.001)


def wtr050_recordstart(chan):
    wtr050_sendbyte(0xff)
    time.sleep(0.01)
    wtr050_sendbyte(0x55)
    time.sleep(0.01)
    wtr050_sendbyte(0x01)
    time.sleep(0.01)
    wtr050_sendbyte(chan)
    time.sleep(0.01)

def wtr050_recordstop():
    wtr050_sendbyte(0xff)
    time.sleep(0.01)
    wtr050_sendbyte(0x55)
    time.sleep(0.01)
    wtr050_sendbyte(0x02)
    time.sleep(0.01)
    time.sleep(0.2)


def wtr050_playvoice(chan):
    wtr050_sendbyte(0xff)
    time.sleep(0.01)
    wtr050_sendbyte(0x55)
    time.sleep(0.01)
    wtr050_sendbyte(0x03)
    time.sleep(0.01)
    wtr050_sendbyte(chan)
    time.sleep(0.01)

def wtr050_stopvoice():
    wtr050_sendbyte(0xff)
    time.sleep(0.01)
    wtr050_sendbyte(0x55)
    time.sleep(0.01)
    wtr050_sendbyte(0x04)
    time.sleep(0.01)
    time.sleep(0.1)


#WIFI 模块
RevBuf = ["-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1"]



def iCloudMemory_Serial_Init(pin1,pin2):
    global WIFI_Tx, WIFI_Rx
    WIFI_Tx = pin1
    WIFI_Rx = pin2
    global ser
    ser=serial.Serial("/dev/ttyAMA0",9600,timeout=0.5) #使用树莓派的GPIO口连接串行口
    ser.flushInput()
    time.sleep(0.1)
    iCloudMemory_iCloud_Read_String("000000000000", 1)
    return ser

def iCloudMemory_WiFi_SSIDPWD_Config(SSID, PASSWORD):
    buf = [0]

    while True:
        while True:
            ser.write("#".encode('utf-8'))
            ser.write("#".encode('utf-8'))
            ser.write("#".encode('utf-8'))
            ser.write(SSID.encode('utf-8'))
            for i in range(20-len(SSID)):
                ser.write(b'')
            ser.write(PASSWORD.encode('utf-8'))
            for i in range(20-len(PASSWORD)):
                ser.write(b'')
            ser.write("\r\n".encode('utf-8'));
            time.sleep(0.5)
            Rcv = str(ser.read(ser.in_waiting),encoding = "utf-8")
            print(Rcv)
            if Rcv == "":
                break
        if Rcv.find("OK") < 0:
            break

def wifi_sendbyte(text):
    ser.write((text + "\n").encode('utf-8'))#向端口些数据

def wifi_readbyte():
    a = ''
    while(1):
        a = bytes.decode(ser.readline()[1:])
        if a != '':
            break
    return a

def iCloudMemory_iCloud_Read_String(MACaddr,addr):
    rev = ''
    revtmp = ''
    Timeout = 0
    while str(ser.readline(), encoding = "utf-8") != "":
        continue
    if MACaddr == "000000000000":
        ser.write('000000000000'.encode('utf-8'))
        ser.write("&R".encode('utf-8'))
        str1 = str(addr) + '\r\n'
        ser.write(str1.encode('utf-8'))
        Timeout = 0

        while True:
            revtmp = str(ser.read(1), encoding = "utf-8")

            rev += revtmp
            Timeout = Timeout + 1
            if (Timeout >= 30):
                return RevBuf[addr]
            time.sleep(0.01)

            if revtmp =='':

                break
        RevBuf[addr] = rev
    else:
        if (addr > 0 and addr < 21):
            ser.write(MACaddr.encode('utf-8'))
            ser.write("&R".encode('utf-8'))
            ser.write(str(addr).encode('utf-8'))
            ser.write('\r\n'.encode('utf-8'))

            Timeout = 0
            while True:
                revtmp = str(ser.readline(), encoding = "utf-8")
                rev += revtmp
                Timeout = Timeout + 1
                if (Timeout >= 30) :
                    return RevBuf[addr];
                time.sleep(0.01)
                if revtmp == "":
                    break
            RevBuf[addr] = rev
        else:
            #basic.showNumber(2);
            RevBuf[addr] = "-1";
    return RevBuf[addr]

def iCloudMemory_iCloud_Read_Float(MACaddr,addr):
    rev = ''
    revtmp = ''
    Timeout = 0
    while str(ser.readline(), encoding = "utf-8") != "":
        continue
    if MACaddr == "000000000000":
        ser.write("000000000000".encode('utf-8'))
        ser.write("&R".encode('utf-8'))
        str1 = str(addr) + '\r\n'
        ser.write(str1.encode('utf-8'))
        Timeout = 0
        while True:
            revtmp = str(ser.readline(), encoding = "utf-8")
            rev += revtmp
            Timeout = Timeout + 1
            if (Timeout >= 30):
                return float(RevBuf[addr]);
            time.sleep(0.01)

            if revtmp =='':
                break
        RevBuf[addr] = rev
    else:
        if (addr > 0 and addr < 21):
            ser.write(MACaddr.encode('utf-8'))
            ser.write("&R".encode('utf-8'))
            ser.write(str(addr).encode('utf-8'))
            ser.write('\r\n'.encode('utf-8'))

            Timeout = 0
            while True:
                revtmp = str(ser.readline(), encoding = "utf-8")
                rev += revtmp
                Timeout = Timeout + 1
                if (Timeout >= 30) :
                    return float(RevBuf[addr]);
                time.sleep(0.01)
                if revtmp == "":
                    break
            RevBuf[addr] = rev
        else:
            #basic.showNumber(2);
            return float(RevBuf[addr])
    return float(RevBuf[addr])

def iCloudMemory_iCloud_Write_str(data,addr):
    if (addr > 0 and addr < 21) :
        while (ser.readline() != "".encode('utf-8')):
            continue
        ser.write("&W".encode('utf-8'))
        ser.write(str(addr).encode('utf-8'))
        ser.write(" ".encode('utf-8'))
        str1 = data + '\r\n'
        ser.write(str1.encode('utf-8'))

def iCloudMemory_iCloud_Write_num(data,addr):
    if (addr > 0 and addr < 21) :
        while (ser.readline() != "".encode('utf-8')):
            continue
        ser.write("&W".encode('utf-8'))
        ser.write(str(addr).encode('utf-8'))
        ser.write(" ".encode('utf-8'))
        str1 = str(data) + '\r\n'
        ser.write(str1.encode('utf-8'))

def iCloudMemory_iCloudShare_Write_str(data,addr):
    while (ser.readline() != "".encode('utf-8')):
        print(1)
        continue
    ser.write("&S".encode('utf-8'))
    ser.write("000000000000".encode('utf-8'))
    ser.write(" ".encode('utf-8'))
    ser.write(str(addr).encode('utf-8'))
    ser.write(" ".encode('utf-8'))
    str1 = data + '\r\n'
    ser.write(str1.encode('utf-8'))

def iCloudMemory_iCloudShare_Write_num(data,addr):
    while (ser.readline() != "".encode('utf-8')):
        print(1)
        continue
    ser.write("&S".encode('utf-8'))
    ser.write("000000000000".encode('utf-8'))
    ser.write(" ".encode('utf-8'))
    ser.write(str(addr).encode('utf-8'))
    ser.write(" ".encode('utf-8'))
    str1 = str(data) + '\r\n'
    ser.write(str1.encode('utf-8'))

def iCloudMemory_iCloudCommon_Read_Str(addr):
    return iCloudMemory_iCloud_Read_String("000000000000", addr)

def iCloudMemory_iCloudCommon_Read_Num(addr):
    return iCloudMemory_iCloud_Read_Float("000000000000", addr)